# -*- coding:utf-8 -*-
from flask import render_template, redirect, url_for, flash, session, request, abort
from functools import wraps
from werkzeug.utils import secure_filename
import os
import uuid
from datetime import datetime

from . import admin
from app.admin.forms import LoginForm, TagForm, MovieForm, PreviewForm, PwdForm, AuthForm, RoleForm, AdminForm
from app.models import Admin, Tag, Movie, Preview, User, Comment, MovieCol, OpLog, AdminLog, UserLog, Auth, Role
from app import db, app


# 上下文处理器
@admin.context_processor
def tpl_extra():
    data = dict(
        online_time=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    )
    return data


def admin_login_required(func):
    @wraps(func)
    def decorated_function(*args, **kwargs):
        if 'admin' not in session:
            return redirect(url_for('admin.login', next=request.url))
        return func(*args, **kwargs)

    return decorated_function


# 权限控制装饰器
def admin_auth(func):
    @wraps(func)
    def decorated_function(*args, **kwargs):
        admin = Admin.query.join(Role).filter(Role.id == Admin.role_id, Admin.id == session['admin_id']).first()
        auths = admin.role.auths
        auths = list(map(lambda v: int(v), auths.split(',')))
        auth_list = Auth.query.all()
        urls = [v.url for v in auth_list for val in auths if val == v.id]
        rule = request.url_rule
        if str(rule) not in urls:
            abort(404)
        return func(*args, **kwargs)

    return decorated_function


@admin.route("/")
@admin_login_required
def index():
    """首页"""
    return render_template('/admin/index.html')


@admin.route("/login", methods=['GET', 'POST'])
def login():
    """登录页"""
    form = LoginForm()
    if form.validate_on_submit():
        data = form.data
        admin = Admin.query.filter_by(name=data['account']).first()
        if not admin.check_pwd(data['pwd']):
            flash("密码错误! ", 'error')
            return redirect(url_for('admin.login'))
        session['admin'] = data['account']
        session['admin_id'] = admin.id
        admin_log = AdminLog(admin_id=admin.id, ip=request.remote_addr)
        db.session.add(admin_log)
        db.session.commit()
        return redirect(request.args.get('next') or url_for('admin.index'))
    return render_template('/admin/login.html', form=form)


@admin.route("/logout")
@admin_login_required
def logout():
    """退出"""
    session.pop('admin', None)
    session.pop('admin_id', None)
    return redirect(url_for('admin.login'))


@admin.route("/pwd", methods=['GET', 'POST'])
@admin_login_required
def pwd():
    """修改密码"""
    form = PwdForm()
    if form.validate_on_submit():
        data = form.data
        admin = Admin.query.filter_by(name=session['admin']).first()
        from werkzeug.security import generate_password_hash
        admin.pwd = generate_password_hash(data['new_pwd'])
        db.session.add(admin)
        db.session.commit()
        flash('修改密码成功, 请重新登录! ', 'success')
        return redirect(url_for('admin.logout'))
    return render_template('/admin/pwd.html', form=form)


@admin.route("/tag/add", methods=['GET', 'POST'])
@admin_login_required
@admin_auth
def tag_add():
    """添加标签"""
    form = TagForm()
    if form.validate_on_submit():
        data = form.data
        tag = Tag(name=data['name'])
        db.session.add(tag)
        db.session.commit()
        flash("添加标签成功! ", "success")
        oplog = OpLog(admin_id=session['admin_id'], ip=request.remote_addr, reason='添加标签%s' % data['name'])
        db.session.add(oplog)
        db.session.commit()
        redirect(url_for('admin.tag_add'))
    return render_template('/admin/tag_add.html', form=form)


@admin.route("/tag/list/<int:page>", methods=['GET'])
@admin_login_required
@admin_auth
def tag_list(page=None):
    """标签列表页"""
    if page is None:
        page = 1
    page_data = Tag.query.order_by(Tag.id.desc()).paginate(page=page, per_page=3)
    return render_template('/admin/tag_list.html', page_data=page_data)


@admin.route("/tag/del/<int:id>/", methods=['GET'])
@admin_login_required
@admin_auth
def tag_del(id=None):
    """标签删除"""
    tag = Tag.query.filter_by(id=id).first_or_404()
    db.session.delete(tag)
    db.session.commit()
    flash("删除标签成功! ", 'success')
    return redirect(url_for('admin.tag_list', page=1))


@admin.route("/tag/edit/<int:id>", methods=['GET', 'POST'])
@admin_login_required
@admin_auth
def tag_edit(id=None):
    """标签编辑"""
    tag = Tag.query.get_or_404(id)
    form = TagForm()
    if form.validate_on_submit():
        data = form.data
        tag.name = data['name']
        db.session.add(tag)
        db.session.commit()
        flash('标签修改成功! ', 'success')
    return render_template('admin/tag_edit.html', form=form, tag=tag)


def change_filename(filename):
    fileinfo = os.path.split(filename)  # abc.txt  -->  ('abc', '.txt')
    filename = datetime.now().strftime('%Y%m%d%H%M%S') + str(uuid.uuid4().hex) + fileinfo[1]
    return filename


@admin.route("/movie/add", methods=['GET', 'POST'])
@admin_login_required
def movie_add():
    """添加电影"""
    form = MovieForm()
    if form.validate_on_submit():
        data = form.data
        movie_url = secure_filename(form.url.data.filename)
        movie_logo = secure_filename(form.logo.data.filename)
        if not os.path.exists(app.config['UP_DIR']):
            os.makedirs(app.config['UP_DIR'])
            os.chmod(app.config['UP_DIR'], 777)
        url = change_filename(movie_url)
        logo = change_filename(movie_logo)
        form.url.data.save(app.config['UP_DIR'] + url)
        form.logo.data.save(app.config['UP_DIR'] + logo)
        movie = Movie(title=data['title'], url=url, info=data['info'],
                      logo=logo, star=int(data['star']), playnum=0, commentnum=0,
                      tag_id=int(data['tag_id']), area=data['area'],
                      release_time=data['release_time'], length=data['length'])
        db.session.add(movie)
        db.session.commit()
        flash('添加电影成功', 'success')
    return render_template('/admin/movie_add.html', form=form)


@admin.route("/movie/list/<int:page>", methods=['GET'])
@admin_login_required
def movie_list(page=None):
    """电影列表"""
    if page is None:
        page = 1
    page_data = Movie.query.join(Tag).filter(Tag.id == Movie.tag_id).order_by(Movie.addtime.desc()).paginate(page=page,
                                                                                                             per_page=3)
    return render_template('/admin/movie_list.html', page_data=page_data)


@admin.route("/movie/del/<int:id>", methods=['GET'])
@admin_login_required
def movie_del(id=None):
    movie = Movie.query.get_or_404(int(id))
    os.remove(app.config['UP_DIR'] + movie.url)
    os.remove(app.config['UP_DIR'] + movie.logo)
    db.session.delete(movie)
    db.session.commit()
    flash('删除电影成功', 'success')
    return redirect(url_for('admin.movie_list', page=1))


@admin.route("/movie/edit/<int:id>", methods=['GET', 'POST'])
@admin_login_required
def movie_edit(id=None):
    """电影编辑"""
    form = MovieForm()
    form.url.validators = []
    form.logo.validators = []
    movie = Movie.query.get_or_404(id)
    if request.method == 'GET':
        form.info.data = movie.info
        form.tag_id.data = movie.tag_id
        form.star.data = movie.star
    if form.validate_on_submit():
        data = form.data
        if not os.path.exists(app.config['UP_DIR']):
            os.makedirs(app.config['UP_DIR'])
            os.chmod(app.config['UP_DIR'], 777)

        if form.url.data.filename != "":
            movie_url = secure_filename(form.url.data.filename)
            movie.url = change_filename(movie_url)
            form.url.data.save(app.config['UP_DIR'] + movie.url)

        if form.logo.data.filename != "":
            movie_logo = secure_filename(form.logo.data.filename)
            movie.logo = change_filename(movie_logo)
            form.url.data.save(app.config['UP_DIR'] + movie.logo)

        movie.star = data['star']
        movie.tag_id = data['tag_id']
        movie.info = data['info']
        movie.title = data['title']
        movie.area = data['area']
        movie.length = data['length']
        movie.release_time = data['release_time']
        db.session.add(movie)
        db.session.commit()
        flash('标签修改成功! ', 'success')
        return redirect(url_for('admin.movie_edit', id=id))
    return render_template('admin/movie_edit.html', form=form, movie=movie)


@admin.route("/preview/add", methods=['GET', 'POST'])
@admin_login_required
def preview_add():
    """添加预告"""
    form = PreviewForm()
    if form.validate_on_submit():
        data = form.data
        preview_logo = secure_filename(form.logo.data.filename)
        if not os.path.exists(app.config['UP_DIR']):
            os.makedirs(app.config['UP_DIR'])
            os.chmod(app.config['UP_DIR'], 777)
        logo = change_filename(preview_logo)
        form.logo.data.save(app.config['UP_DIR'] + logo)
        preview = Preview(title=data['title'], logo=logo)
        db.session.add(preview)
        db.session.commit()
        flash('添加预告成功! ', 'success')
        return redirect(url_for('admin.preview_add'))
    return render_template('admin/preview_add.html', form=form)


@admin.route("/preview/list/<int:page>", methods=['GET'])
@admin_login_required
def preview_list(page=None):
    """预告列表"""
    if page is None:
        page = 1
    page_data = Preview.query.order_by(Preview.addtime.desc()).paginate(page=page, per_page=3)
    return render_template('admin/preview_list.html', page_data=page_data)


@admin.route("/preview/del/<int:id>", methods=['GET'])
@admin_login_required
def preview_del(id=None):
    preview = Preview.query.get_or_404(id)
    os.remove(app.config['UP_DIR'] + preview.logo)
    db.session.delete(preview)
    db.session.commit()
    flash('删除预告成功! ', 'success')
    return redirect(url_for('admin.preview_list', page=1))


@admin.route("/preview/edit/<int:id>", methods=['GET', 'POST'])
@admin_login_required
def preview_edit(id=None):
    form = PreviewForm()
    form.logo.validators = []
    form.title.validators = []
    preview = Preview.query.get_or_404(id)
    if request.method == 'GET':
        form.title.data = preview.title
    if form.validate_on_submit():
        data = form.data
        if form.logo.data.filename != "":
            preview_logo = secure_filename(form.logo.data.filename)
            preview.logo = change_filename(preview_logo)
            form.url.data.save(app.config['UP_DIR'] + preview.logo)

        preview.title = data['title']
        db.session.add(preview)
        db.session.commit()
        flash('修改预告成功! ', 'success')
        return redirect(url_for('admin.preview_edit', id=id))
    return render_template('admin/preview_edit.html', form=form, preview=preview)


@admin.route("/user/list/<int:page>", methods=['GET'])
@admin_login_required
def user_list(page=None):
    """会员列表"""
    if page is None:
        page = 1
    page_data = User.query.order_by(User.addtime.desc()).paginate(page=page, per_page=3)
    return render_template('admin/user_list.html', page_data=page_data)


@admin.route("/user/view/<int:id>", methods=['GET'])
@admin_login_required
def user_view(id=None):
    """会员查看"""
    user = User.query.get_or_404(id)
    return render_template('admin/user_view.html', user=user)


@admin.route("/user/del/<int:id>", methods=['GET'])
@admin_login_required
def user_del(id=None):
    """会员删除"""
    user = User.query.get_or_404(id)
    db.session.delete(user)
    db.session.commit()
    flash("删除会员成功! ", 'success')
    return redirect(url_for('admin.user_list', page=1))


@admin.route("/comment/list/<int:page>", methods=['GET'])
@admin_login_required
def comment_list(page=None):
    """评论列表"""
    if page is None:
        page = 1
    page_data = Comment.query.join(Movie).join(User).filter(Movie.id == Comment.movie_id,
                                                            User.id == Comment.user_id).order_by(
        Comment.addtime.desc()).paginate(page=page, per_page=3)
    return render_template('admin/comment_list.html', page_data=page_data)


@admin.route("/comment/del/<int:id>", methods=['GET'])
@admin_login_required
def comment_del(id=None):
    """评论删除"""
    comment = Comment.query.get_or_404(id)
    db.session.delete(comment)
    db.session.commit()
    flash("删除评论成功! ", 'success')
    return redirect(url_for('admin.comment_list', page=1))


@admin.route("/moviecol/list/<int:page>", methods=['GET'])
@admin_login_required
def moviecol_list(page=None):
    """收藏列表"""
    if page is None:
        page = 1
    page_data = MovieCol.query.join(Movie).join(User).filter(Movie.id == MovieCol.movie_id,
                                                             User.id == MovieCol.user_id).order_by(
        MovieCol.addtime.desc()).paginate(page=page, per_page=3)
    return render_template('admin/moviecol_list.html', page_data=page_data)


@admin.route("/moviecol/del/<int:id>", methods=['GET'])
@admin_login_required
def moviecol_del(id=None):
    """评论删除"""
    moviecol = MovieCol.query.get_or_404(id)
    db.session.delete(moviecol)
    db.session.commit()
    flash("删除收藏成功! ", 'success')
    return redirect(url_for('admin.moviecol_list', page=1))


@admin.route("/oplog/list/<int:page>", methods=['GET'])
@admin_login_required
def oplog_list(page=None):
    """操作日志列表"""
    if page is None:
        page = 1
    page_data = OpLog.query.join(Admin).filter(Admin.id == OpLog.admin_id).order_by(OpLog.addtime.desc()).paginate(
        page=page, per_page=3)

    return render_template('admin/oplog_list.html', page_data=page_data)


@admin.route("/adminloginlog/list/<int:page>", methods=['GET'])
@admin_login_required
def adminloginlog_list(page=None):
    """管理员登录日志列表"""
    if page is None:
        page = 1
    page_data = AdminLog.query.join(Admin).filter(Admin.id == AdminLog.admin_id).order_by(
        AdminLog.addtime.desc()).paginate(page=page, per_page=3)
    return render_template('admin/adminloginlog_list.html', page_data=page_data)


@admin.route("/userloginlog/list/<int:page>", methods=['GET'])
@admin_login_required
def userloginlog_list(page=None):
    """会员登录日志列表"""
    if page is None:
        page = 1
    page_data = UserLog.query.join(User).filter(User.id == UserLog.user_id).order_by(
        UserLog.addtime.desc()).paginate(page=page, per_page=3)
    return render_template('admin/userloginlog_list.html', page_data=page_data)


@admin.route("/role/add", methods=['GET', 'POST'])
@admin_login_required
def role_add():
    """添加角色"""
    form = RoleForm()
    if form.validate_on_submit():
        data = form.data
        role = Role(name=data['name'], auths=','.join(map(lambda v: str(v), data['auths'])))
        db.session.add(role)
        db.session.commit()
        flash('添加角色成功! ', 'success')
        return redirect(url_for('admin.role_add'))
    return render_template('admin/role_add.html', form=form)


@admin.route("/role/list/<int:page>", methods=['GET'])
@admin_login_required
def role_list(page=None):
    """角色列表"""
    if page is None:
        page = 1
    page_data = Role.query.order_by(Role.addtime.desc()).paginate(page=page, per_page=3)
    return render_template('admin/role_list.html', page_data=page_data)


@admin.route("/role/del/<int:id>", methods=['GET'])
@admin_login_required
def role_del(id=None):
    """角色删除"""
    role = Role.query.get_or_404(id)
    db.session.delete(role)
    db.session.commit()
    flash('角色删除成功! ', 'success')
    return redirect(url_for('admin.role_list', page=1))


@admin.route("/role/edit/<int:id>", methods=['GET', 'POST'])
@admin_login_required
def role_edit(id=None):
    """角色编辑"""
    form = RoleForm()
    role = Role.query.get_or_404(id)
    if request.method == 'GET':
        form.auths.data = list(map(lambda v: int(v), role.auths.split(',')))
    if form.validate_on_submit():
        data = form.data
        role.name = data['name']
        role.auths = ','.join(map(lambda v: str(v), data['auths']))
        db.session.add(role)
        db.session.commit()
        flash('角色修改成功! ', 'success')
        redirect(url_for('admin.role_edit', id=id))
    return render_template('admin/role_edit.html', form=form, role=role)


@admin.route("/auth/add", methods=['GET', 'POST'])
@admin_login_required
def auth_add():
    """权限添加"""
    form = AuthForm()
    if form.validate_on_submit():
        data = form.data
        auth = Auth(name=data['name'], url=data['url'])
        db.session.add(auth)
        db.session.commit()
        flash("权限添加成功! ", 'success')
        return redirect(url_for('admin.auth_add'))
    return render_template('admin/auth_add.html', form=form)


@admin.route("/auth/list/<int:page>", methods=['GET'])
@admin_login_required
def auth_list(page=None):
    """权限列表"""
    if page is None:
        page = 1
    page_data = Auth.query.order_by(Auth.addtime.desc()).paginate(page=page, per_page=3)
    return render_template('admin/auth_list.html', page_data=page_data)


@admin.route("/auth/del/<int:id>", methods=['GET'])
@admin_login_required
def auth_del(id=None):
    """删除权限"""
    auth = Auth.query.get_or_404(id)
    db.session.delete(auth)
    db.session.commit()
    flash('权限删除成功! ', 'success')
    return redirect(url_for('admin.auth_list', page=1))


@admin.route("/auth/edit/<int:id>", methods=['GET', 'POST'])
@admin_login_required
def auth_edit(id=None):
    """编辑权限"""
    form = AuthForm()
    auth = Auth.query.get_or_404(id)
    if form.validate_on_submit():
        data = form.data
        auth.name = data['name']
        auth.url = data['url']
        db.session.add(auth)
        db.session.commit()
        flash('权限修改成功! ', 'success')
        redirect(url_for('admin.auth_edit', id=id))
    return render_template('admin/auth_edit.html', form=form, auth=auth)


@admin.route("/admin/add", methods=['GET', 'POST'])
@admin_login_required
def admin_add():
    """添加管理员"""
    form = AdminForm()
    from werkzeug.security import generate_password_hash
    if form.validate_on_submit():
        data = form.data
        admin = Admin(name=data['name'], pwd=generate_password_hash(data['pwd']), role_id=data['role_id'], is_super=1)
        db.session.add(admin)
        db.session.commit()
        flash('添加管理员成功! ', 'success')
    return render_template('admin/admin_add.html', form=form)


@admin.route("/admin/list/<int:page>", methods=['GET'])
@admin_login_required
def admin_list(page=None):
    """管理员列表"""
    if page is None:
        page = 1
    page_data = Admin.query.join(Role).filter(Role.id == Admin.role_id).order_by(Admin.addtime.desc()).paginate(
        page=page, per_page=3)
    return render_template('admin/admin_list.html', page_data=page_data)
